/**
 * @file		terminal_command.c
 * @brief		Observe Terminal Command
 * @note		None
 * @attention	None
 * 
 * <B><I>ALL RIGHTS RESERVED, COPYRIGHT&copy; SOCIONEXT INCORPORATED 2016</I></B>
 */

/* Standard includes. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"

/* Base Function includes */
#include "statemachine.h"
#include "uart.h"
#include "CMDinterpreter.h"

/* Component Test includes */
#if 0	// CM0 Driver debug
#include "ct_dd_pmc_adc.h"
#include "ct_dd_pmc_calendar.h"
#include "ct_dd_pmc_ctc.h"
#include "ct_dd_pmc_temp_sensor_if.h"
#endif


#define MAX_OF_CMD_LINE		(256)

typedef void (*CTMain)(int iArgc, char** ppcArgv);	// component test main.

static char cmd_string[MAX_OF_CMD_LINE];

static void prvMemDump(int argc, char** argv)
{
	unsigned long ulPosition = 0;
	unsigned long ulAddress = strtoul(argv[1], NULL, 16);
	unsigned long ulSize = strtoul(argv[2], NULL, 16);

	if ((ulAddress == 0) || (ulSize < 0x10)) {
		return;
	}
	
	printf("---- memory dump ----\n");
	while (ulPosition < ulSize) {
		printf( "0x%08X : 0x%08X 0x%08X 0x%08X 0x%08X\n",
				(unsigned int)(ulAddress + ulPosition),
				(unsigned int)*((unsigned long*)(ulAddress + ulPosition)),
				(unsigned int)*((unsigned long*)(ulAddress + ulPosition + 4)),
				(unsigned int)*((unsigned long*)(ulAddress + ulPosition + 8)),
				(unsigned int)*((unsigned long*)(ulAddress + ulPosition + 12)) );
		ulPosition += 0x10;
	}
	printf("---------------------\n");
}

static void prvCommandWrapper(CTMain pxMainFunction, char* pcCommand)
{
	int		iArgc = 0;
	char*	pcArgv[16];
	long	iPos = 0;
	long	iLen = 0;
	long	iMax = strlen(pcCommand);
	long	iLoop;

	// Set arg buffer
	for(iLoop = 0; iLoop < iMax; iLoop++){
		if(pcCommand[iLoop] == ' '){
			if(iLen){
				pcArgv[iArgc] = &pcCommand[iPos];
				pcCommand[iLoop] = '\0';
				iArgc++;
				iLen = 0;
			}
			iPos = iLoop + 1;
		}
		else if(iLoop == iMax - 1){
			pcArgv[iArgc] = &pcCommand[iPos];
			iArgc++;
			break;
		}
		else{
			iLen++;
		}
	}
	
	// Execute command
	pxMainFunction(iArgc, pcArgv);
}

void vTerminalTask( void *pvParameters )
{
	int iResult = 0;

	putchar('\n'); putchar('$'); putchar(' '); fflush(stdout);		/* pgr0695 */

	for(;;) {
		iResult = iUARTReadTerminal(cmd_string);
		if (0 != iResult) {
			vTaskDelay( 200 );
			continue;
		}
		
		if( 0 == strncmp( cmd_string, "state ", 6 ) ) {
			char *pStr;
			pStr = cmd_string + 6;
			if( 0 == strncmp( pStr, "go ", 3 ) ) {
				int res;
				unsigned tmp;
				pStr += 3;
				tmp = ((unsigned)*pStr)-'0';
				printf( "start iStateMachineSetState(%d)\n", tmp );
				res = iStateMachineSetState( (E_STATEMACHINE_STATE)tmp );
				printf( "terminal command : response = %d\n", res );
			}
		}
#if 0	// CM0 Driver debug
		else if( 0 == strncmp( cmd_string, "adc ", 4 ) ) {
			// ADC Driver.
			prvCommandWrapper(Ct_Dd_Pmc_Adc_Main, cmd_string);
		}
		else if( 0 == strncmp( cmd_string, "calendar ", 9 ) ) {
			// Calendar Driver.
			prvCommandWrapper(Ct_Dd_Pmc_Calendar_Main, cmd_string);
		}
		else if( 0 == strncmp( cmd_string, "ctc ", 4 ) ) {
			// CTC Driver.
			prvCommandWrapper(Ct_Dd_Pmc_Ctc_Main, cmd_string);
		}
		else if( 0 == strncmp( cmd_string, "tsif ", 5) ) {
			// Temperature Sensor IF Driver.
			prvCommandWrapper(Ct_Dd_Pmc_TS_IF_Main, cmd_string);
		}
		else if( 0 == strncmp( cmd_string, "flag ", 5) ) {
			// test : set event flag.
			int shift = 0;
			switch (cmd_string[5]) {
				case '1':
					shift = 1;
					break;
				case '2':
					shift = 2;
					break;
				case '3':
					shift = 3;
					break;
				case '4':
					shift = 4;
					break;
				case '5':
					shift = 5;
					break;
				case '6':
					shift = 6;
					break;
				case '7':
					shift = 7;
					break;
				default:
					break;
			}
			xEventGroupSetBits(xNotifyEventFlag, (1 << shift));
		}
#endif
		else if( 0 == strncmp( cmd_string, "dump ", 5) ) {
			// memory dump.
			prvCommandWrapper(prvMemDump, cmd_string);
		}
		else {
			// illegal command.
			memset(cmd_string, 0, MAX_OF_CMD_LINE);
			continue;
		}
		putchar('\n'); putchar('$'); putchar(' '); fflush(stdout);		/* pgr0695 */
		memset(cmd_string, 0, MAX_OF_CMD_LINE);
	}
}
